package cn.tedu.mall.order.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.pojo.domain.CsmallAuthenticationInfo;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.order.mapper.OmsCartMapper;
import cn.tedu.mall.order.service.IOmsCartService;
import cn.tedu.mall.pojo.order.dto.CartAddDTO;
import cn.tedu.mall.pojo.order.dto.CartUpdateDTO;
import cn.tedu.mall.pojo.order.model.OmsCart;
import cn.tedu.mall.pojo.order.vo.CartStandardVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class OmsCartServiceImpl implements IOmsCartService {
    @Autowired
    private OmsCartMapper omsCartMapper;
    //新增sku信息到购物车
    @Override
    public void addCart(CartAddDTO cartDTO) {
        /*要实现新增购物车信息，要先判断这个skuId是否已经在当前用户购物车中包含了
        * 那么就必须先获取当前登录用户的userId
        * 需要编写方法从Spring Security上下文获取*/
        Long userId = getUserId();
        //根据userId和cartDTO参数中skuId进行查询
        OmsCart omsCart = omsCartMapper.selectExistsCart(userId,cartDTO.getSkuId());
        //如果omsCart查询不为空，则表示这个商品已经存在于购物车了
        if (omsCart == null){
            //如果为空,表示购物车没有这个商品,进行新增操作
            // 我们需要将cartDTO中的同名输出赋值到omsCart中,以便进行新增
            // 但是omsCart是null的话,赋值的过程会报null指针,所以要先实例化
            omsCart = new OmsCart();
            BeanUtils.copyProperties(cartDTO,omsCart);
            // cartDTO中没有userId的信息,需要单独赋值
            omsCart.setUserId(userId);
            //执行新增
            omsCartMapper.saveCart(omsCart);
        }else {
            // omsCart不是null,就要对当前购物车中商品进行数量的修改
            // 数量的值是当前购物车中数量+cartDTO参数中新增的数量
            // 因为数据库修改操作直接是赋值,所以在连库前,需要把数量加好
            // 我们将omsCart中的数量和cartDTO中的数量相加,在赋值给omsCart对象的quantity属性
            omsCart.setQuantity(cartDTO.getQuantity()+omsCart.getQuantity());
            omsCartMapper.updateQuantityById(omsCart);
        }
    }

    @Override
    public JsonPage<CartStandardVO> listCarts(Integer page, Integer pageSize) {
        Long userId = getUserId();
        //设置查询分页的数据范围
        PageHelper.startPage(page,pageSize);
        //上面完成后，下面的查询操作会自动添加limit关键字在sql语句末尾
        List<CartStandardVO> list = omsCartMapper.selectCartsByUserId(userId);
        //返回JsonPage类型对象
        return JsonPage.restPage(new PageInfo<>(list));
    }

    @Override
    public void removeCart(Long[] ids) {
        int rows = omsCartMapper.deleteCartsByIds(ids);
        if (rows == 0){
            throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,"您要删除的商品已经被删除了");
        }
    }

    @Override
    public void removeAllCarts() {
        Long userId = getUserId();
        int rows = omsCartMapper.deleteCartsByUserId(userId);
        if (rows == 0){
            throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,"您的购物车为空");
        }
    }

    @Override
    public void removeUserCarts(OmsCart omsCart) {
        //直接调用删除购物车中的方法即可，无需受影响的行数，也不抛出异常，购物车删除失败也不影响新增订单的流程
        omsCartMapper.deleteCartByUserIdAndSkuId(omsCart);

    }

    @Override
    public void updateQuantity(CartUpdateDTO cartUpdateDTO) {
        OmsCart omsCart = new OmsCart();
        BeanUtils.copyProperties(cartUpdateDTO,omsCart);
        omsCartMapper.updateQuantityById(omsCart);
    }

    /*如果需要在业务逻辑层中获取用户信息
    * 就可以编写下面的方法，从spring security上下文获取
    * 这个用户信息是以JWT的方式从前端发到控制器，我们的过滤器会解析JWT
    * 并将解析出来的用户信息保存到Spring Security上下文中*/
    public CsmallAuthenticationInfo getUserInfo(){
        //获取spring Security上下文
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        if (authenticationToken == null){
            throw new CoolSharkServiceException(ResponseCode.UNAUTHORIZED,"您还未登录");
        }
        //从spring security上下文获取用户信息
        CsmallAuthenticationInfo csmallAuthenticationInfo = (CsmallAuthenticationInfo) authenticationToken.getCredentials();
        return csmallAuthenticationInfo;
    }
    //业务逻辑层实际开发时，大部分都是需要用户id而已，所有直接编写方法，返回用户id
    public Long getUserId(){
        return getUserInfo().getId();
    }
}
